// Content script for Element Capture Assistant extension

(function () {
  if (window.webElementSelector) {
    return;
  }

  class WebElementSelector {
    constructor() {
      this.isActive = false;
      this.isSelecting = false;
      this.isRecording = true;
      this.selectedElements = [];
      this.currentHighlightedElement = null;
      this.panel = null;
      this.tooltip = null;
      this.editedCellValues = new Map();
      this.boundMouseOver = this.handleMouseOver.bind(this);
      this.boundMouseOut = this.handleMouseOut.bind(this);
      this.boundClick = this.handleClick.bind(this);
      this.boundKeyDown = this.handleKeyDown.bind(this);
      this.loadConfig();
      this.initialize();
    }

    // Initialize the extension
    initialize() {
      this.removeAllEventListeners();

      // Listen for messages from the background script
      chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
        if (message.action === "toggleSelector") {
          this.toggleSelector();
          if (sendResponse) {
            sendResponse({ status: "success" });
          }
          return true;
        }
      });

      console.log("Element Capture Assistant 已初始化");
    }

    loadConfig() {
      chrome.storage.sync.get({
        siteSelectors: this.siteSelectors
      }, (items) => {
        this.siteSelectors = items.siteSelectors;
      });
    }

    saveConfig() {
      chrome.storage.sync.set({
        siteSelectors: this.siteSelectors
      }, () => {
        console.log('配置已保存');
      });
    }

    // Toggle the selector on/off
    toggleSelector() {
      if (this.isActive) {
        this.deactivate();
      } else {
        this.activate();
      }
    }

    // Activate the selector
    activate() {
      if (this.isActive) return;

      this.isActive = true;
      this.isSelecting = true;

      // Create the panel
      this.createPanel();

      // Create the tooltip
      this.createTooltip();

      // Add event listeners
      document.addEventListener('mouseover', this.boundMouseOver);
      document.addEventListener('mouseout', this.boundMouseOut);
      document.addEventListener('click', this.boundClick, true);
      document.addEventListener('keydown', this.boundKeyDown);

      console.log("Element Capture Assistant 已激活");
    }

    // Deactivate the selector
    deactivate() {
      if (!this.isActive) return;

      this.isActive = false;
      this.isSelecting = false;

      // Remove the panel
      if (this.panel) {
        document.body.removeChild(this.panel);
        this.panel = null;
      }

      // Remove the tooltip
      if (this.tooltip) {
        document.body.removeChild(this.tooltip);
        this.tooltip = null;
      }

      this.removeAllEventListeners();
      this.removeAllHighlights();
      this.selectedElements = [];

      console.log("Element Capture Assistant 已停用");
    }

    // Remove all event listeners
    removeAllEventListeners() {
      document.removeEventListener('mouseover', this.boundMouseOver);
      document.removeEventListener('mouseout', this.boundMouseOut);
      document.removeEventListener('click', this.boundClick, true);
      document.removeEventListener('keydown', this.boundKeyDown);
    }

    // Create the floating panel
    createPanel() {
      const existingPanel = document.getElementById('web-element-selector-panel');
      if (existingPanel) {
        document.body.removeChild(existingPanel);
      }

      // Create the panel
      this.panel = document.createElement('div');
      this.panel.id = 'web-element-selector-panel';
      this.panel.style.position = 'fixed';
      this.panel.style.top = '20px';
      this.panel.style.right = '20px';
      this.panel.style.zIndex = '10000000';
      this.panel.style.cursor = 'default';
      this.panel.style.width = '800px';
      this.panel.style.height = '300px';
      this.panel.style.minWidth = '400px';
      this.panel.style.minHeight = '200px';
      this.panel.style.boxSizing = 'border-box';
      this.panel.style.overflow = 'hidden';
      this.panel.style.display = 'flex';
      this.panel.style.flexDirection = 'column';

      // Create the header
      const header = document.createElement('div');
      header.id = 'web-element-selector-header';
      header.textContent = 'Element Capture Assistant';
      header.style.cursor = 'move';
      header.style.userSelect = 'none';
      header.style.flexShrink = '0';

      let isDragging = false;
      let dragOffsetX = 0;
      let dragOffsetY = 0;
      header.addEventListener('mousedown', (e) => {
        isDragging = true;
        const rect = this.panel.getBoundingClientRect();
        dragOffsetX = e.clientX - rect.left;
        dragOffsetY = e.clientY - rect.top;
        document.body.style.userSelect = 'none';
      });
      document.addEventListener('mousemove', (e) => {
        if (isDragging) {
          this.panel.style.left = (e.clientX - dragOffsetX) + 'px';
          this.panel.style.top = (e.clientY - dragOffsetY) + 'px';
          this.panel.style.right = 'auto';
        }
      });
      document.addEventListener('mouseup', () => {
        isDragging = false;
        document.body.style.userSelect = '';
      });

      // Create the close button
      const closeButton = document.createElement('span');
      closeButton.id = 'web-element-selector-close';
      closeButton.textContent = '×';
      closeButton.addEventListener('click', () => this.deactivate());
      header.appendChild(closeButton);

      // Create the URL section
      const url = document.createElement('div');
      url.id = 'web-element-selector-url';
      url.textContent = window.location.href;
      url.style.flexShrink = '0';

      const contentContainer = document.createElement('div');
      contentContainer.style.display = 'flex';
      contentContainer.style.flexDirection = 'column';
      contentContainer.style.flex = '1';
      contentContainer.style.overflow = 'hidden';

      // Create the list of selected elements
      const list = document.createElement('div');
      list.id = 'web-element-selector-list';
      list.style.minHeight = '100px';
      list.style.overflowY = 'auto';
      list.style.flex = '1';

      // Create the actions section
      const actions = document.createElement('div');
      actions.id = 'web-element-selector-actions';
      actions.style.flexShrink = '0';
      actions.style.marginTop = '10px';
      actions.style.display = 'flex';
      actions.style.justifyContent = 'flex-end';
      actions.style.flexWrap = 'wrap';

      const toggleRecordingButton = document.createElement('button');
      toggleRecordingButton.className = 'web-element-selector-button';
      toggleRecordingButton.textContent = this.isRecording ? '非录制模式' : '录制模式';
      toggleRecordingButton.addEventListener('click', () => {
        this.isRecording = !this.isRecording;
        toggleRecordingButton.textContent = this.isRecording ? '非录制模式' : '录制模式';
      });

      const findAllButton = document.createElement('button');
      findAllButton.className = 'web-element-selector-button';
      findAllButton.textContent = '一键获取元素';
      findAllButton.addEventListener('click', () => this.findAllInteractiveElements());

      // Create the export buttons
      const exportCsvButton = document.createElement('button');
      exportCsvButton.className = 'web-element-selector-button';
      exportCsvButton.textContent = '导出CSV';
      exportCsvButton.addEventListener('click', () => this.exportToCsv());

      const exportJsonButton = document.createElement('button');
      exportJsonButton.className = 'web-element-selector-button';
      exportJsonButton.textContent = '导出JSON';
      exportJsonButton.addEventListener('click', () => this.exportToJson());

      const exportYamlButton = document.createElement('button');
      exportYamlButton.className = 'web-element-selector-button';
      exportYamlButton.textContent = '导出YAML';
      exportYamlButton.addEventListener('click', () => this.exportToYaml());

      const copyButton = document.createElement('button');
      copyButton.className = 'web-element-selector-button';
      copyButton.textContent = '复制';
      copyButton.addEventListener('click', () => this.copyToClipboard());

      // Add all elements to the panel
      actions.appendChild(toggleRecordingButton);
      actions.appendChild(findAllButton);
      actions.appendChild(exportCsvButton);
      actions.appendChild(exportJsonButton);
      actions.appendChild(exportYamlButton);
      actions.appendChild(copyButton);

      contentContainer.appendChild(list);
      contentContainer.appendChild(actions);

      this.panel.appendChild(header);
      this.panel.appendChild(url);
      this.panel.appendChild(contentContainer);

      const resizeHandle = document.createElement('div');
      resizeHandle.className = 'web-element-selector-resize-handle';
      resizeHandle.style.position = 'absolute';
      resizeHandle.style.right = '0';
      resizeHandle.style.bottom = '0';
      resizeHandle.style.width = '15px';
      resizeHandle.style.height = '15px';
      resizeHandle.style.cursor = 'nwse-resize';
      resizeHandle.style.backgroundImage = 'linear-gradient(135deg, transparent 10px, rgba(0,0,0,0.3) 11px, transparent 11px)';
      resizeHandle.style.backgroundSize = '12px 12px';
      resizeHandle.style.backgroundRepeat = 'no-repeat';
      resizeHandle.style.backgroundPosition = 'right bottom';
      resizeHandle.style.zIndex = '10';

      let isResizing = false;
      let originalWidth, originalHeight, originalX, originalY;

      resizeHandle.addEventListener('mousedown', (e) => {

        e.stopPropagation();

        isResizing = true;
        const rect = this.panel.getBoundingClientRect();
        originalWidth = rect.width;
        originalHeight = rect.height;
        originalX = e.clientX;
        originalY = e.clientY;
        document.body.style.userSelect = 'none';
      });

      document.addEventListener('mousemove', (e) => {
        if (!isResizing) return;

        const newWidth = Math.max(400, originalWidth + (e.clientX - originalX));
        const newHeight = Math.max(200, originalHeight + (e.clientY - originalY));
        this.panel.style.width = newWidth + 'px';
        this.panel.style.height = newHeight + 'px';
      });

      document.addEventListener('mouseup', () => {
        if (isResizing) {
          isResizing = false;
          document.body.style.userSelect = '';
        }
      });

      this.panel.appendChild(resizeHandle);

      // Add the panel to the page
      document.body.appendChild(this.panel);

      // Show the panel
      this.panel.style.display = 'flex';
    }

    // Create the tooltip for showing locators
    createTooltip() {
      const existingTooltip = document.querySelector('.web-element-selector-tooltip');
      if (existingTooltip) {
        document.body.removeChild(existingTooltip);
      }

      this.tooltip = document.createElement('div');
      this.tooltip.className = 'web-element-selector-tooltip';
      this.tooltip.style.display = 'none';
      document.body.appendChild(this.tooltip);
    }

    // Handle mouse over event
    handleMouseOver(event) {
      if (!this.isSelecting) return;

      // Prevent highlighting the panel or tooltip
      if (event.target.closest('#web-element-selector-panel') ||
        event.target.closest('.web-element-selector-tooltip')) {
        return;
      }

      // Highlight the element
      this.highlightElement(event.target);

      // Show the tooltip with locators
      this.showLocatorsTooltip(event.target, event.clientX, event.clientY);
    }

    // Handle mouse out event
    handleMouseOut(event) {
      if (!this.isSelecting) return;

      // Remove the highlight
      this.removeHighlight(event.target);

      // Hide the tooltip
      this.hideTooltip();
    }

    // Handle click event
    handleClick(event) {
      if (!this.isSelecting) return;

      // Prevent clicking on the panel or tooltip
      if (event.target.closest('#web-element-selector-panel') ||
        event.target.closest('.web-element-selector-tooltip')) {
        return;
      }

      if (this.isRecording) {
        event.preventDefault();
        event.stopPropagation();

        if (this.selectedElements.includes(event.target)) {
          this.deselectElement(event.target);
        } else {
          this.selectElement(event.target);
        }
      }
    }

    // Handle key down event (Escape to exit)
    handleKeyDown(event) {
      if (event.key === 'Escape') {
        this.deactivate();
      }
    }

    // Highlight an element
    highlightElement(element) {
      if (this.currentHighlightedElement === element) return;

      // Remove highlight from the previous element
      if (this.currentHighlightedElement) {
        this.removeHighlight(this.currentHighlightedElement);
      }

      // Highlight the new element
      element.classList.add('web-element-selector-highlight');
      this.currentHighlightedElement = element;
    }

    // Remove highlight from an element
    removeHighlight(element) {
      element.classList.remove('web-element-selector-highlight');

      if (this.currentHighlightedElement === element) {
        this.currentHighlightedElement = null;
      }
    }

    // Remove all highlights
    removeAllHighlights() {
      const highlightedElements = document.querySelectorAll('.web-element-selector-highlight');
      highlightedElements.forEach(element => {
        element.classList.remove('web-element-selector-highlight');
      });

      const selectedElements = document.querySelectorAll('.web-element-selector-selected');
      selectedElements.forEach(element => {
        element.classList.remove('web-element-selector-selected');

        const badge = element.querySelector('.web-element-selector-badge');
        if (badge) {
          element.removeChild(badge);
        }
      });

      this.currentHighlightedElement = null;
    }

    // Select an element
    selectElement(element) {
      if (this.selectedElements.includes(element)) {
        return;
      }

      this.selectedElements.push(element);
      element.classList.add('web-element-selector-selected');
      this.addElementToPanel(element);

      const badge = document.createElement('div');
      badge.className = 'web-element-selector-badge';
      badge.textContent = this.selectedElements.length;

      const existingBadge = element.querySelector('.web-element-selector-badge');
      if (existingBadge) {
        element.removeChild(existingBadge);
      }

      element.appendChild(badge);


    }

    // Add an element to the panel
    addElementToPanel(element) {
      const list = document.getElementById('web-element-selector-list');

      if (list.children.length === 0) {
        const locatorTypes = ['#', '推荐定位器', 'ID', 'Tag Name', 'Class Name', 'CSS', 'XPath', 'Link Text', 'Name'];

        const headerRow = document.createElement('div');
        headerRow.className = 'web-element-selector-header-row';

        locatorTypes.forEach(type => {
          const headerCell = document.createElement('div');
          headerCell.className = 'web-element-selector-header-cell';
          headerCell.textContent = type;

          if (type === '#') {
            headerCell.style.flex = '0 0 40px';
            headerCell.style.minWidth = '40px';
            headerCell.style.textAlign = 'center';
          }

          const resizer = document.createElement('div');
          resizer.className = 'web-element-selector-header-cell-resizer';
          headerCell.appendChild(resizer);

          this.addResizerEvents(resizer);

          headerRow.appendChild(headerCell);
        });
        list.appendChild(headerRow);
      }

      const item = document.createElement('div');
      item.className = 'web-element-selector-item';

      const locators = this.generateLocators(element);
      const aquaLocator = this.generateAquaLocator(element);
      const locatorTypes = ['#', '推荐定位器', 'ID', 'Tag Name', 'Class Name', 'CSS', 'XPath', 'Link Text', 'Name'];
      const rowNumber = list.querySelectorAll('.web-element-selector-item').length + 1;

      locatorTypes.forEach(type => {
        const cell = document.createElement('div');
        cell.className = 'web-element-selector-cell';

        if (type === '#') {
          cell.textContent = rowNumber;
          cell.style.flex = '0 0 40px';
          cell.style.minWidth = '40px';
          cell.style.textAlign = 'center';
        }
        else if (type === '推荐定位器') {
          const editedValue = this.getCellEditedValue(element, type);

          if (editedValue) {
            cell.textContent = editedValue;
            cell.style.color = '#1976d2';
            cell.style.fontWeight = 'bold';
          } else if (aquaLocator) {
            cell.textContent = aquaLocator;
            cell.style.color = '#1976d2';
            cell.style.fontWeight = 'bold';
          } else {
            cell.textContent = '无唯一推荐定位器';
            cell.style.color = '#d32f2f';
            cell.style.fontStyle = 'italic';
          }

          cell.ondblclick = (e) => this.handleCellEdit(e, element, type, cell);
        } else {
          const editedValue = this.getCellEditedValue(element, type);
          cell.textContent = editedValue || locators[type] || '';

          cell.ondblclick = (e) => this.handleCellEdit(e, element, type, cell);
        }

        item.appendChild(cell);
      });

      list.appendChild(item);
    }

    generateLocators(element) {
      const locators = {
        ID: "",
        Name: "",
        "Class Name": "",
        "Tag Name": element.tagName.toLowerCase(),
        "Link Text": "",
        CSS: this.getSimpleCssSelector(element),
        XPath: this.getSimpleXPath(element)
      };

      if (element.id) {
        locators.ID = element.id;
      }

      if (element.name) {
        locators.Name = element.name;
      }

      if (element.className && element.className.trim() !== '') {
        const allClassNames = element.className.split(' ').filter(c => {
          return c !== '' &&
            c !== 'web-element-selector-highlight' &&
            c !== 'web-element-selector-selected';
        });

        if (allClassNames.length > 0) {
          locators["Class Name"] = allClassNames.join(' ');
        }
      }

      if (element.tagName.toLowerCase() === 'a' && element.textContent && element.textContent.trim() !== '') {
        const text = element.textContent.trim();
        const processedText = this.truncateString(text, 50);

        if (processedText) {
          locators["Link Text"] = processedText;
        }
      }

      return locators;
    }

    getSimpleCssSelector(element) {
      if (!element) return '';
      const tag = element.tagName.toLowerCase();

      if (element.id) {
        return `${tag}#${element.id}`;
      }

      if (element.name) {
        return `${tag}[name="${element.name}"]`;
      }

      for (const attr of ['role', 'aria-label', 'title', 'placeholder']) {
        if (element.getAttribute(attr)) {
          const attrValue = element.getAttribute(attr);
          return `${tag}[${attr}="${attrValue}"]`;
        }
      }

      const classes = element.className.split(' ').filter(c => {
        return c !== '' &&
          c !== 'web-element-selector-highlight' &&
          c !== 'web-element-selector-selected';
      });

      if (classes.length > 0) {
        return `${tag}.${classes[0]}`;
      }

      const parent = element.parentElement;
      if (parent && parent.id) {
        const siblings = Array.from(parent.children).filter(e => e.tagName === element.tagName);
        if (siblings.length === 1) {
          return `#${parent.id} > ${tag}`;
        } else {
          const index = siblings.indexOf(element) + 1;
          return `#${parent.id} > ${tag}:nth-child(${index})`;
        }
      }

      return `${tag}:nth-of-type(${this.getNthOfType(element)})`;
    }

    getNthOfType(element) {
      if (!element) return 1;
      let count = 0;
      let sibling = element;

      while (sibling) {
        if (sibling.nodeType === Node.ELEMENT_NODE && sibling.tagName === element.tagName) {
          count++;
        }
        sibling = sibling.previousElementSibling;
      }

      return count;
    }

    getSimpleXPath(element) {
      if (!element) return '';

      if (element.id) {
        return `//${element.tagName.toLowerCase()}[@id="${element.id}"]`;
      }

      if (element.name) {
        return `//${element.tagName.toLowerCase()}[@name="${element.name}"]`;
      }


      const classes = element.className.split(' ').filter(c => {
        return c !== '' &&
          c !== 'web-element-selector-highlight' &&
          c !== 'web-element-selector-selected';
      });

      if (classes.length > 0) {
        return `//${element.tagName.toLowerCase()}[contains(@class, "${classes[0]}")]`;
      }

      if (element.textContent && element.textContent.trim() !== '') {
        const text = element.textContent.trim();
        const processedText = this.truncateString(text, 30).replace(/['"`]/g, '');

        if (processedText) {
          return `//${element.tagName.toLowerCase()}[contains(text(), "${processedText}")]`;
        }
      }

      for (const attr of ['role', 'aria-label', 'title', 'placeholder']) {
        if (element.getAttribute(attr)) {
          const attrValue = element.getAttribute(attr);
          return `//${element.tagName.toLowerCase()}[@${attr}="${attrValue}"]`;
        }
      }

      const parent = element.parentElement;
      if (parent) {
        if (parent.id) {
          return `//*[@id="${parent.id}"]/${element.tagName.toLowerCase()}[${this.getElementIndex(element)}]`;
        } else {
          const index = this.getElementIndex(element);
          const parentPath = this.getParentPath(parent, 2);
          return `${parentPath}/${element.tagName.toLowerCase()}[${index}]`;
        }
      }

      return `//${element.tagName.toLowerCase()}[${this.getElementIndex(element)}]`;
    }


    getElementIndex(element) {
      if (!element || !element.parentNode) return 1;

      let count = 1;
      let sibling = element.previousSibling;

      while (sibling) {
        if (sibling.nodeType === Node.ELEMENT_NODE && sibling.tagName === element.tagName) {
          count++;
        }
        sibling = sibling.previousSibling;
      }

      return count;
    }

    getParentPath(element, maxLevels = 2) {
      if (!element || maxLevels <= 0) return '';

      if (element.id) {
        return `//*[@id="${element.id}"]`;
      }

      if (element === document.body) {
        return '/html/body';
      }

      if (element.parentElement) {
        return this.getParentPath(element.parentElement, maxLevels - 1) +
          `/${element.tagName.toLowerCase()}[${this.getElementIndex(element)}]`;
      }

      return `/${element.tagName.toLowerCase()}[${this.getElementIndex(element)}]`;
    }

    // Show locators in a tooltip
    showLocatorsTooltip(element, x, y) {
      const aquaLocator = this.generateAquaLocator(element);
      let content = '<div><strong>推荐定位器：</strong></div>';
      if (aquaLocator) {
        content += `<div style=\"color:#1976d2;font-weight:bold;\">${aquaLocator}</div>`;
      } else {
        content += `<div style=\"color:#d32f2f;font-weight:bold;\">无唯一推荐定位器</div>`;
      }
      const locators = this.generateLocators(element);
      const locatorTypes = ['ID', 'Name', 'Class Name', 'Tag Name', 'Link Text', 'CSS', 'XPath'];
      content += '<div style=\"margin-top:6px;\"><strong>其他可用定位器：</strong></div>';
      for (const type of locatorTypes) {
        if (locators[type]) {
          content += `<div>${type}: ${locators[type]}</div>`;
        }
      }
      this.tooltip.innerHTML = content;
      this.tooltip.style.top = `${y + 20}px`;
      this.tooltip.style.left = `${x + 10}px`;
      this.tooltip.style.display = 'block';
    }

    // Hide the tooltip
    hideTooltip() {
      if (this.tooltip) {
        this.tooltip.style.display = 'none';
      }
    }

    // Export the selected elements to CSV
    exportToCsv() {
      if (this.selectedElements.length === 0) {
        alert('尚未选择任何元素。');
        return;
      }

      let csv = '#,元素类型,推荐定位器,ID,Tag Name,Class Name,CSS,XPath,Link Text,Name\n';

      this.selectedElements.forEach((element, index) => {
        const locators = this.generateLocators(element);
        const editedAquaLocator = this.getCellEditedValue(element, '推荐定位器');
        const aquaLocator = editedAquaLocator || this.generateAquaLocator(element) || '无唯一推荐定位器';
        const idValue = this.getCellEditedValue(element, 'ID') || locators.ID;
        const tagValue = this.getCellEditedValue(element, 'Tag Name') || locators["Tag Name"];
        const classValue = this.getCellEditedValue(element, 'Class Name') || locators["Class Name"];
        const cssValue = this.getCellEditedValue(element, 'CSS') || locators.CSS;
        const xpathValue = this.getCellEditedValue(element, 'XPath') || locators.XPath;
        const linkTextValue = this.getCellEditedValue(element, 'Link Text') || locators["Link Text"];
        const nameValue = this.getCellEditedValue(element, 'Name') || locators.Name;
        const rowNumber = index + 1;

        csv += `${rowNumber},${element.tagName.toLowerCase()},"${aquaLocator}",${idValue},${tagValue},"${classValue}","${cssValue}","${xpathValue}","${linkTextValue}",${nameValue}\n`;
      });

      // Create a blob and download the file
      const blob = new Blob([csv], { type: 'text/csv' });
      const url = URL.createObjectURL(blob);

      const a = document.createElement('a');
      a.href = url;
      a.download = `web-elements-${this.formatDate()}.csv`;
      a.click();

      URL.revokeObjectURL(url);
    }

    exportToJson() {
      if (this.selectedElements.length === 0) {
        alert('尚未选择任何元素。');
        return;
      }

      const elements = [];

      this.selectedElements.forEach((element, index) => {
        const locators = this.generateLocators(element);
        const editedAquaLocator = this.getCellEditedValue(element, '推荐定位器');
        const aquaLocator = editedAquaLocator || this.generateAquaLocator(element) || '无唯一推荐定位器';
        const idValue = this.getCellEditedValue(element, 'ID') || locators.ID;
        const tagValue = this.getCellEditedValue(element, 'Tag Name') || locators["Tag Name"];
        const classValue = this.getCellEditedValue(element, 'Class Name') || locators["Class Name"];
        const cssValue = this.getCellEditedValue(element, 'CSS') || locators.CSS;
        const xpathValue = this.getCellEditedValue(element, 'XPath') || locators.XPath;
        const linkTextValue = this.getCellEditedValue(element, 'Link Text') || locators["Link Text"];
        const nameValue = this.getCellEditedValue(element, 'Name') || locators.Name;
        const rowNumber = index + 1;

        elements.push({
          "#": rowNumber,
          elementType: element.tagName.toLowerCase(),
          text: element.textContent.trim().substring(0, 50),
          locators: {
            "推荐定位器": aquaLocator,
            ID: idValue,
            "Tag Name": tagValue,
            "Class Name": classValue,
            CSS: cssValue,
            XPath: xpathValue,
            "Link Text": linkTextValue,
            Name: nameValue
          }
        });
      });

      const json = JSON.stringify({
        url: window.location.href,
        timestamp: new Date().toISOString(),
        elements: elements
      }, null, 2);

      const blob = new Blob([json], { type: 'application/json' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `web-elements-${this.formatDate()}.json`;
      a.click();

      URL.revokeObjectURL(url);
    }

    exportToYaml() {
      if (this.selectedElements.length === 0) {
        alert('尚未选择任何元素。');
        return;
      }

      const elements = [];

      this.selectedElements.forEach((element, index) => {
        const locators = this.generateLocators(element);
        const editedAquaLocator = this.getCellEditedValue(element, '推荐定位器');
        const aquaLocator = editedAquaLocator || this.generateAquaLocator(element) || '无唯一推荐定位器';
        const idValue = this.getCellEditedValue(element, 'ID') || locators.ID;
        const tagValue = this.getCellEditedValue(element, 'Tag Name') || locators["Tag Name"];
        const classValue = this.getCellEditedValue(element, 'Class Name') || locators["Class Name"];
        const cssValue = this.getCellEditedValue(element, 'CSS') || locators.CSS;
        const xpathValue = this.getCellEditedValue(element, 'XPath') || locators.XPath;
        const linkTextValue = this.getCellEditedValue(element, 'Link Text') || locators["Link Text"];
        const nameValue = this.getCellEditedValue(element, 'Name') || locators.Name;
        const rowNumber = index + 1;

        elements.push({
          "#": rowNumber,
          elementType: element.tagName.toLowerCase(),
          text: element.textContent.trim().substring(0, 50),
          locators: {
            "推荐定位器": aquaLocator,
            ID: idValue,
            "Tag Name": tagValue,
            "Class Name": classValue,
            CSS: cssValue,
            XPath: xpathValue,
            "Link Text": linkTextValue,
            Name: nameValue
          }
        });
      });

      const data = {
        url: window.location.href,
        timestamp: new Date().toISOString(),
        elements: elements
      };

      let yaml = "---\n";
      yaml += `url: ${data.url}\n`;
      yaml += `timestamp: ${data.timestamp}\n`;
      yaml += "elements:\n";

      elements.forEach(element => {
        yaml += `  - "#": ${element["#"]}\n`;
        yaml += `    elementType: ${element.elementType}\n`;
        yaml += `    text: ${element.text.replace(/"/g, '\\"')}\n`;
        yaml += "    locators:\n";
        yaml += `      推荐定位器: ${element.locators["推荐定位器"] ? '"' + element.locators["推荐定位器"].replace(/"/g, '\\"') + '"' : 'null'}\n`;
        yaml += `      ID: ${element.locators.ID || 'null'}\n`;
        yaml += `      Tag Name: ${element.locators["Tag Name"] || 'null'}\n`;
        yaml += `      Class Name: ${element.locators["Class Name"] ? '"' + element.locators["Class Name"].replace(/"/g, '\\"') + '"' : 'null'}\n`;
        yaml += `      CSS: ${element.locators.CSS ? '"' + element.locators.CSS.replace(/"/g, '\\"') + '"' : 'null'}\n`;
        yaml += `      XPath: ${element.locators.XPath ? '"' + element.locators.XPath.replace(/"/g, '\\"') + '"' : 'null'}\n`;
        yaml += `      Link Text: ${element.locators["Link Text"] ? '"' + element.locators["Link Text"].replace(/"/g, '\\"') + '"' : 'null'}\n`;
        yaml += `      Name: ${element.locators.Name || 'null'}\n`;
      });

      const blob = new Blob([yaml], { type: 'text/yaml' });
      const url = URL.createObjectURL(blob);

      const a = document.createElement('a');
      a.href = url;
      a.download = `web-elements-${this.formatDate()}.yaml`;
      a.click();

      URL.revokeObjectURL(url);
    }

    copyToClipboard() {
      if (this.selectedElements.length === 0) {
        alert('尚未选择任何元素。');
        return;
      }

      const elements = this.selectedElements.map(element => {
        const locators = this.generateLocators(element);

        const editedAquaLocator = this.getCellEditedValue(element, '推荐定位器');
        const aquaLocator = editedAquaLocator || this.generateAquaLocator(element);

        const idValue = this.getCellEditedValue(element, 'ID') || locators.ID;
        const nameValue = this.getCellEditedValue(element, 'Name') || locators.Name;
        const classValue = this.getCellEditedValue(element, 'Class Name') || locators["Class Name"];
        const tagValue = this.getCellEditedValue(element, 'Tag Name') || locators["Tag Name"];

        const mainIdentifier = aquaLocator ? `推荐定位器 = ${aquaLocator}` :
          idValue ? `ID = ${idValue}` :
            nameValue ? `Name = ${nameValue}` :
              classValue ? `Class = ${classValue}` :
                `Tag = ${tagValue}`;

        return `${element.tagName.toLowerCase()}: ${mainIdentifier}`;
      });

      const text = elements.join('\n');

      // Copy to clipboard
      navigator.clipboard.writeText(text).then(() => {
        alert('已复制到剪贴板！');
      }).catch(err => {
        console.error('复制失败:', err);
        alert('复制失败，请检查浏览器权限。');
      });
    }

    // Format date for filenames
    formatDate() {
      const date = new Date();
      return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
    }

    truncateString(str, maxLength) {
      if (str.length <= maxLength) {
        return str;
      }
      return str.substring(0, maxLength) + '...';
    }

    deselectElement(element) {
      const badge = element.querySelector('.web-element-selector-badge');
      if (badge) {
        element.removeChild(badge);
      }

      const removedIndex = this.selectedElements.indexOf(element);

      this.selectedElements = this.selectedElements.filter(el => el !== element);

      element.classList.remove('web-element-selector-selected');

      if (removedIndex !== -1) {

        for (let i = removedIndex; i < this.selectedElements.length; i++) {
          const el = this.selectedElements[i];
          const badgeEl = el.querySelector('.web-element-selector-badge');
          if (badgeEl) {
            badgeEl.textContent = i + 1;
          }
        }
      }

      const list = document.getElementById('web-element-selector-list');
      if (list) {

        const locators = this.generateLocators(element);
        const cssSelector = locators.CSS;
        const xpathSelector = locators.XPath;
        const aquaLocator = this.generateAquaLocator(element);

        let itemToRemove = null;
        let itemToRemoveIndex = -1;

        Array.from(list.children).forEach((item, index) => {

          if (index === 0 && item.className === 'web-element-selector-header-row') {
            return;
          }

          if (item.className === 'web-element-selector-item') {
            const cells = item.querySelectorAll('.web-element-selector-cell');
            let shouldRemove = false;

            if (aquaLocator && cells[1] && cells[1].textContent === aquaLocator) {
              shouldRemove = true;
            } else if (locators.ID && cells[2] && cells[2].textContent === locators.ID) {
              shouldRemove = true;
            } else if (locators.Name && cells[8] && cells[8].textContent === locators.Name) {
              shouldRemove = true;
            } else if (cssSelector && cells[5] && cells[5].textContent === cssSelector) {
              shouldRemove = true;
            } else if (xpathSelector && cells[6] && cells[6].textContent === xpathSelector) {
              shouldRemove = true;
            }

            if (shouldRemove) {
              itemToRemove = item;
              itemToRemoveIndex = index;
              return;
            }
          }
        });

        if (itemToRemove) {
          list.removeChild(itemToRemove);

          Array.from(list.children).forEach((item, index) => {
            if (index === 0 && item.className === 'web-element-selector-header-row') {
              return;
            }

            if (index >= itemToRemoveIndex && item.className === 'web-element-selector-item') {
              const cells = item.querySelectorAll('.web-element-selector-cell');
              if (cells[0]) {

                let rowIndex = 0;
                for (let i = 0; i < index; i++) {
                  if (list.children[i].className === 'web-element-selector-item') {
                    rowIndex++;
                  }
                }
                cells[0].textContent = rowIndex + 1;
              }
            }
          });
        }
      }
    }

    addResizerEvents(resizer) {
      resizer.addEventListener('mousedown', (startEvent) => {
        startEvent.preventDefault();
        startEvent.stopPropagation();

        const headerCell = resizer.parentElement;
        const columnIndex = Array.from(headerCell.parentElement.children).indexOf(headerCell);
        const initialX = startEvent.clientX;
        const initialWidth = headerCell.offsetWidth;
        let newWidth;

        const list = document.getElementById('web-element-selector-list');
        const allRows = list.children;

        const mouseMoveHandler = (moveEvent) => {
          moveEvent.preventDefault();
          const deltaX = moveEvent.clientX - initialX;
          newWidth = Math.max(80, initialWidth + deltaX); // 最小宽度为80px

          headerCell.style.width = `${newWidth}px`;
          headerCell.style.flex = 'none';

          for (let i = 1; i < allRows.length; i++) {
            const row = allRows[i];
            if (row.className === 'web-element-selector-item') {
              const cells = row.children;
              if (columnIndex < cells.length) {
                cells[columnIndex].style.width = `${newWidth}px`;
                cells[columnIndex].style.flex = 'none';
              }
            }
          }
        };

        const mouseUpHandler = () => {
          document.removeEventListener('mousemove', mouseMoveHandler);
          document.removeEventListener('mouseup', mouseUpHandler);
        };

        document.addEventListener('mousemove', mouseMoveHandler);
        document.addEventListener('mouseup', mouseUpHandler);
      });
    }

    generateAquaLocator(element) {
      const semanticAttrs = ['data-testid', 'aria-label', 'role', 'placeholder', 'alt', 'title'];
      for (const attr of semanticAttrs) {
        const value = element.getAttribute && element.getAttribute(attr);
        if (value) {
          const selector = `[${attr}="${value}"]`;
          if (this.isUniqueSelector(selector, element)) {
            return selector;
          }
        }
      }

      const tag = element.tagName.toLowerCase();
      const text = element.innerText?.trim();
      if (text && text.length > 0 && ['button', 'a', 'span', 'div', 'li', 'p'].includes(tag)) {
        const shortText = text.length > 30 ? text.substring(0, 30) : text;
        if (!shortText.match(/["'`]/)) {
          const selector = `${tag}:has-text(\"${shortText}\")`;
          if (this.isUniqueSelector(selector, element)) {
            return selector;
          }
        }
      }

      const cssSelector = this.getSimpleCssSelector(element);
      if (cssSelector && this.isUniqueSelector(cssSelector, element)) {
        return cssSelector;
      }
      let parent = element.parentElement;
      let deep = 0;
      while (parent && deep < 2) {
        if (parent.id) {
          const selector = `#${parent.id} > ${tag}`;
          if (this.isUniqueSelector(selector, element)) {
            return selector;
          }
        }
        parent = parent.parentElement;
        deep++;
      }

      const xpath = this.getSimpleXPath(element);
      if (this.isUniqueXPath(xpath, element)) {
        return xpath;
      }

      return '';
    }

    isUniqueSelector(selector, element) {
      try {
        const nodes = document.querySelectorAll(selector);
        return nodes.length === 1 && nodes[0] === element;
      } catch {
        return false;
      }
    }

    isUniqueXPath(xpath, element) {
      try {
        const result = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
        return result.snapshotLength === 1 && result.snapshotItem(0) === element;
      } catch {
        return false;
      }
    }

    getCellKey(element, type) {
      const id = element.id || '';
      const tag = element.tagName || '';
      const className = element.className || '';
      return `${id}_${tag}_${className}_${type}`;
    }

    getCellEditedValue(element, type) {
      const key = this.getCellKey(element, type);
      return this.editedCellValues.get(key);
    }

    setCellEditedValue(element, type, value) {
      const key = this.getCellKey(element, type);
      this.editedCellValues.set(key, value);
    }

    handleCellEdit(event, element, type, cell) {
      event.stopPropagation();

      if (cell.querySelector('input') || cell.querySelector('textarea')) {
        return;
      }

      const originalValue = cell.textContent;

      const isLongText = originalValue.length > 50;
      const input = document.createElement(isLongText ? 'textarea' : 'input');

      input.value = originalValue;
      input.className = 'web-element-selector-cell-editor';
      input.style.width = '100%';
      input.style.height = isLongText ? '60px' : '20px';
      input.style.boxSizing = 'border-box';
      input.style.padding = '2px 4px';
      input.style.fontFamily = 'inherit';
      input.style.fontSize = 'inherit';

      cell.textContent = '';
      cell.appendChild(input);

      input.focus();
      input.select();

      const saveEdit = () => {
        const newValue = input.value.trim();

        this.setCellEditedValue(element, type, newValue);

        cell.textContent = newValue;

        if (type === '推荐定位器') {
          cell.style.color = '#1976d2';
          cell.style.fontWeight = 'bold';
        }
      };

      const cancelEdit = () => {
        cell.textContent = originalValue;

        if (type === '推荐定位器') {
          cell.style.color = '#1976d2';
          cell.style.fontWeight = 'bold';
        }
      };

      input.onblur = () => {
        saveEdit();
      };

      input.onkeydown = (e) => {
        if (e.key === 'Enter' && !e.shiftKey) {
          e.preventDefault();
          saveEdit();
          input.blur();
        } else if (e.key === 'Escape') {
          e.preventDefault();
          cancelEdit();
          input.blur();
        }
      };
    }

    findAllInteractiveElements() {
      if (!this.isActive || !this.isRecording) {
        console.log("选择器未激活或不在录制模式，无法一键获取元素。");
        return;
      }

      const interactiveSelectors = 'a, button, input:not([type="hidden"]), select, textarea, [onclick], [role="button"], [tabindex]';

      try {
        const elements = document.querySelectorAll(interactiveSelectors);
        console.log(`找到 ${elements.length} 个潜在的可交互元素。`);

        elements.forEach(element => {
          if (!element.closest('#web-element-selector-panel') &&
            !element.closest('.web-element-selector-tooltip')) {
            this.selectElement(element);
          }
        });

        console.log("一键获取元素完成。");

      } catch (error) {
        console.error("一键获取元素时出错:", error);
      }
    }
  }

  window.webElementSelector = new WebElementSelector();
})(); 